//
//  XCMianThreadMonitor.swift
//  XCFPSMonitor
//
//  Created by mac on 2025/2/17.
//

import Foundation

//主线程监控
class XCMianThreadMonitor {
    static var shared: XCMianThreadMonitor = XCMianThreadMonitor()
    
    private var semaphore: DispatchSemaphore! // 信号量
    private var timeoutCount: Int = 0 // 超时计数器
    private var activity: CFRunLoopActivity! // 记录当前 RunLoop 活动
    private var isMonitoring: Bool = false // 标记监控是否正在进行
    private var runLoopObserver: CFRunLoopObserver? // 保存观察者
    
    private init() {}
    
    // 启动监控
    public func start() {
        guard !isMonitoring else { return } // 如果已经在监控，直接返回
        
        // 设置为正在监控
        isMonitoring = true
        
        // 注册 RunLoop 观察者
        registerObserver()
        
        // 启动监控线程
        startMonitor()
    }
    
    // 停止监控
    public func stop() {
        guard isMonitoring else { return } // 如果没有在监控中，直接返回
        
        // 设置为停止监控
        isMonitoring = false
        
        // 清理信号量
        semaphore.signal() // 释放信号量，允许线程退出
        
        // 移除 RunLoop 观察者
        stopObserver()
    }
}

private extension XCMianThreadMonitor {
    
    // 注册 RunLoop 观察者
    func registerObserver() {
        let controllerPointer = Unmanaged<XCMianThreadMonitor>.passUnretained(self).toOpaque()
        var context = CFRunLoopObserverContext(version: 0, info: controllerPointer, retain: nil, release: nil, copyDescription: nil)
        
        // 创建一个观察者，监听 RunLoop 活动
        runLoopObserver = CFRunLoopObserverCreate(nil, CFRunLoopActivity.allActivities.rawValue, true, 0, { (observer, activity, info) in
            guard let info = info else { return }
            
            let monitor = Unmanaged<XCMianThreadMonitor>.fromOpaque(info).takeUnretainedValue()
            monitor.activity = activity
            monitor.semaphore.signal() // 释放信号量，表示此时主线程有活动
        }, &context)
        
        // 添加观察者到主线程的 RunLoop 中
        if let observer = runLoopObserver {
            CFRunLoopAddObserver(CFRunLoopGetMain(), observer, CFRunLoopMode.commonModes)
        }
    }
    
    // 停止观察 RunLoop
    func stopObserver() {
        // 移除主线程的 RunLoop 观察者
        if let observer = runLoopObserver {
            CFRunLoopRemoveObserver(CFRunLoopGetMain(), observer, CFRunLoopMode.commonModes)
        }
    }
    
    // 启动监控，监听主线程卡顿
    func startMonitor() {
        // 初始化信号量
        semaphore = DispatchSemaphore(value: 0)
        
        // 启动一个子线程进行监控
        DispatchQueue.global().async {
            while self.isMonitoring {
                // 设定超时时间为 1 秒，等待信号量
                let st = self.semaphore.wait(timeout: DispatchTime.now() + 1.0)
                
                // 如果超时，说明主线程可能卡顿
                if st != DispatchTimeoutResult.success {
                    // 检查 RunLoop 的活动状态，判断是否为卡顿状态
                    if self.activity == .beforeSources || self.activity == .afterWaiting {
                        self.timeoutCount += 1
                        
                        if self.timeoutCount >= 2 {
                            // 连续超过两次卡顿，打印卡顿信息
                            let timestamp = Date()
                            let callStack = Thread.callStackSymbols.joined(separator: "\n")
                            print("检测到超过两次连续卡顿，时间: \(timestamp)\n调用栈:\n\(callStack)")
                            self.timeoutCount = 0 // 重置超时计数
                        }
                    }
                } else {
                    // 如果信号量在 1 秒内被触发，重置超时计数
                    self.timeoutCount = 0
                }
                
                // 如果没有在监控，退出循环
                if !self.isMonitoring {
                    break
                }
            }
        }
    }
}
